package codecs;

import java.awt.Dimension;

import javax.media.Buffer;
import javax.media.Codec;
import javax.media.Format;
import javax.media.ResourceUnavailableException;
import javax.media.format.RGBFormat;
import javax.media.format.VideoFormat;
import javax.media.format.YUVFormat;

/**
 * Shows a binary image of the image stream
 * @author	Daniel Mohr, Daniela Grammlich
 */
public class BinaryCodec implements Codec {
	
	/**
	 * The supported input formats
	 */
	protected Format[] supportedInputFormats = new Format[0];
	/**
	 * The supported output formats
	 */
	protected Format[] supportedOutputFormats = new Format[0];
	
	/**
	 * The input format
	 */
	protected VideoFormat inputFormat;
	/**
	 * THe output format
	 */
	protected VideoFormat outputFormat;

	/**
	 * Binary image data
	 */
	private int[][] binary;
	
	/**
	 * Control to access the DifferenceCodec data
	 */
	private DifferenceCodecControlInterface control;
	/**
	 * The name of the codec
	 */
	private static String CODEC_NAME = "BinaryCodec";
	
	/**
	 * Constructor
	 * @param dcci	the control of the DifferenceCodec
	 */
	public BinaryCodec(DifferenceCodecControlInterface dcci) {
		supportedInputFormats = new Format[] {
				new VideoFormat(VideoFormat.RGB, new Dimension(320, 240), 
						230400, Format.byteArray, (float) 15.0),
				new RGBFormat(),
				new YUVFormat(),
		};	
		supportedOutputFormats = new Format[] {
//				new VideoFormat(VideoFormat.RGB)
				new RGBFormat(),
				new YUVFormat(),
		};	
		control = dcci;
	}

	@Override
	public Format[] getSupportedInputFormats() {
		return supportedInputFormats;
	}

	@Override
	public Format[] getSupportedOutputFormats(Format input) {
		if(input == null) {
			return supportedOutputFormats;
		}
		if(input instanceof RGBFormat) {
			return(new Format[] {   
				input,
				supportedOutputFormats[0],
			});
		} else {
			return(supportedOutputFormats);
		}
	}

	@Override
	public synchronized int process(Buffer inputBuffer, Buffer outputBuffer) {
		this.binary = control.getBinary() ;
		outputBuffer.copy(inputBuffer);
		int outputDataLength = ((VideoFormat) outputFormat).getMaxDataLength();
		
		outputBuffer.setLength(outputDataLength);
		outputBuffer.setFormat(outputFormat);
		outputBuffer.setFlags(inputBuffer.getFlags());
		
		int[] outputData = (int[]) outputBuffer.getData();
		
		/* dimension of the incoming stream */
		RGBFormat videoFormatIn = (RGBFormat)inputBuffer.getFormat();
		Dimension sizeIn = videoFormatIn.getSize();
		int height = (int) sizeIn.getHeight();
		int width = (int) sizeIn.getWidth();
		
		/* coloring the stream in black and white */
		for(int x = 0; x < width; x++) {
			for(int y = 0; y < height; y++) {
				if(binary[x][y] == 0) {
					outputData[y * width + x] = 0xFF000000;
				} else if(binary[x][y] == 1){
					outputData[y * width + x] = 0xFFFFFFFF;					
				} else {
					outputData[y * width + x] = binary[x][y];
				}
			}
		}
		return BUFFER_PROCESSED_OK;
	}
	
	@Override
	public Format setInputFormat(Format inputFormat) {
		this.inputFormat = (VideoFormat) inputFormat;
		return (Format) this.inputFormat;
	}

	@Override
	public Format setOutputFormat(Format outputFormat) {
		this.outputFormat = (VideoFormat) outputFormat;
		return (Format) this.outputFormat;
	}

	@Override
	public void close() {
	}

	@Override
	public String getName() {
		return CODEC_NAME;
	}

	@Override
	public void open() throws ResourceUnavailableException {
	}

	@Override
	public void reset() {
		close();
	}

	@Override
	public Object getControl(String controlType) {
		return null;
	}

	@Override
	public Object[] getControls() {
		return null;
	}

}
